package com.scau.yangsuiyu.estore.util;

import java.util.regex.Pattern;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputControl;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;

/**
 * @author suiyu_yang
 * @description 表单验证类
 * @date 2019-05-28 09:36
 * @email suiyu_yang@163.com
 */
public class FormValidate<T extends TextInputControl> {
    private T[] requireControls;// 非空验证目标控件
    private ObservableList<Label> reqLabels = FXCollections.observableArrayList();
    private ObservableList<Label> regLabels = FXCollections.observableArrayList();
    private Label errorLabel;
    public static final String BIGDECIMAL_REG = "^[+-]?\\d+(\\.\\d+)?$"; // BigDecimal类型数据的正则表达式
    public static final String CHINAMOBILENO_REG = "^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$"; // 中国手机号码的正则表达式
    public static final String EMAIL_REG = "^[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}$";
    public static final String DECIMAL_REG = "^[0-9]+(.[0-9]{0,2})?$";

    /**
     * 为表单添加非空验证
     *
     * @param targetControls，目标表单数组
     * @param errorLabels，错误提示文字数组
     * @return，返回验证结果，只要出现一个表单为空，则返回为false
     */
    public void installRequireValidation(T[] targetControls, Label[] errorLabels) {

        // 初始化非空验证目标控件数组
        requireControls = targetControls;

        for (int i = 0, tarCount = targetControls.length; i < tarCount; i++) {
            Label requireLabel = errorLabels[i];
            requireLabel.setVisible(false);
            reqLabels.add(requireLabel);

            // 表单获取焦点时进行验证
            int curIndex = i;
            targetControls[i].focusedProperty().addListener((obVal, oldVal, newVal) -> {
                if (newVal) {
                    if ("".equals(targetControls[curIndex].getText())) {
                        requireLabel.setVisible(true);
                    } else {
                        requireLabel.setVisible(false);
                    }
                }
            });
            // 键入文字时实时验证
            targetControls[i].textProperty().addListener((obVal, oldVal, newVal) -> {

                if ("".equals(newVal)) {
                    requireLabel.setVisible(true);
                } else {
                    requireLabel.setVisible(false);
                }
            });
        }
    }

    /**
     * 为表单添加正则验证
     *
     * @param targetControls,目标表单数组
     * @param regType，正则验证类型
     * @param errorLabel，错误提示标签
     * @return，只要有一个表单未通过正则，则返回就为false
     */
    public void installRegularValidation(T[] targetControls, String regType, Label[] errorLabel) {

        for (int i = 0, tarCount = targetControls.length; i < tarCount; i++) {
            Label regLabel = errorLabel[i];
            regLabel.setVisible(false);
            regLabels.add(regLabel);

            int curIndex = i;
            targetControls[i].textProperty().addListener((obVal, oldVal, newVal) -> {

                // 表单为空时不进行正则验证
                if (!"".equals(newVal) && !Pattern.matches(regType, targetControls[curIndex].getText())) {
                    regLabel.setVisible(true);
                } else {
                    regLabel.setVisible(false);
                }
            });
        }
    }


    /**
     * 为确认密码项添加验证
     *
     * @param passwordPF
     * @param confirmPasswordPF
     * @param errorLabel
     */
    public void installConfirmPswValidation(T passwordPF, T confirmPasswordPF, Label errorLabel) {

        this.errorLabel = errorLabel;
        errorLabel.setVisible(false);

        // password获取焦点时进行验证
        passwordPF.focusedProperty().addListener((obVal, oldVal, newVal) -> {
            if (newVal) {
                if (passwordPF.getText().equals(confirmPasswordPF.getText())) {
                    errorLabel.setVisible(false);
                } else {
                    errorLabel.setVisible(true);
                }
            }
        });

        // confirmPassword获取焦点时进行验证
        confirmPasswordPF.focusedProperty().addListener((obVal, oldVal, newVal) -> {
            if (newVal) {
                if (passwordPF.getText().equals(confirmPasswordPF.getText())) {
                    errorLabel.setVisible(false);
                } else {
                    errorLabel.setVisible(true);
                }
            }
        });

        // 键入文字时实时验证
        confirmPasswordPF.textProperty().addListener((obVal, oldVal, newVal) -> {

            if (newVal.equals(passwordPF.getText())) {
                errorLabel.setVisible(false);
            } else {
                errorLabel.setVisible(true);
            }
        });

        passwordPF.textProperty().addListener((obVal, oldVal, newVal) -> {
            if (newVal.equals(confirmPasswordPF.getText())) {
                errorLabel.setVisible(false);
            } else {
                errorLabel.setVisible(true);
            }
        });

    }

    /**
     * 验证当前所有目标控件
     *
     * @return
     */
    public boolean isValid() {

        /* 触发初始非空验证 */
        if (requireControls != null) {
            for (int i = 0, reqCount = reqLabels.size(); i < reqCount; i++) {

                if (0 == requireControls[i].getLength()) {
                    reqLabels.get(i).setVisible(true);
                } else {
                    reqLabels.get(i).setVisible(false);
                }

            }
        }

        /* 检验所有指定控件是否通过验证 */
        if (regLabels.size() != 0) {
            for (int i = 0, reqLabelSize = reqLabels.size(); i < reqLabelSize; i++) {
                if (reqLabels.get(i).isVisible()) {
                    return false;
                }
            }
        }
        if (regLabels.size() != 0) {
            for (int i = 0, regLabelSize = regLabels.size(); i < regLabelSize; i++) {
                if (regLabels.get(i).isVisible()) {
                    return false;
                }
            }
        }
        if (errorLabel != null) {
            if (errorLabel.isVisible()) {
                return false;
            }

        }
        return true;
    }

}
